home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2004 #9 / Amiga Plus CD - 2004 - No. 09.iso / amigaplus / tools / amigaos4_only / xmess0821 / src / unix / config.c
C/C++ Source or Header  |  2004-08-03  |  22KB  |  800 lines

  1. /*
  2.  * X-mame config-file and commandline parsing
  3.  * We don't use stderr_file resp stdout_file in here since we don't know if 
  4.  * it's valid yet.
  5.  */
  6.  
  7. #define __CONFIG_C_
  8. #include <time.h>
  9. #include "xmame.h"
  10. #include "fileio.h"
  11. #include "driver.h"
  12. #include "audit.h"
  13. #include "sysdep/sysdep_dsp.h"
  14. #include "sysdep/sysdep_mixer.h"
  15. #include "sysdep/misc.h"
  16. #include "effect.h"
  17.  
  18. /* be sure that device names are nullified */
  19. extern void XInput_trackballs_reset();
  20.  
  21. /* from ... */
  22. extern char *cheatfile;
  23. extern char *db_filename;
  24. extern char *history_filename;
  25. extern char *mameinfo_filename;
  26.  
  27. extern char *playbackname;
  28. extern char *recordname;
  29.  
  30. /* some local vars */
  31. static int showconfig = 0;
  32. static int showmanusage = 0;
  33. static int showversion = 0;
  34. static int showusage  = 0;
  35. static int use_fuzzycmp = 1;
  36. static int loadconfig = 1;
  37. static char *language = NULL;
  38. static char *gamename = NULL;
  39. char *rompath_extra = NULL;
  40. #ifndef MESS
  41. static char *defaultgamename;
  42. #else
  43. static const char *mess_opts;
  44. #endif
  45.  
  46. static int config_handle_arg(char *arg);
  47. #ifdef MAME_DEBUG
  48. static int config_handle_debug_size(struct rc_option *option, const char *arg,
  49.         int priority);
  50. #endif
  51. void show_usage(void);
  52.  
  53. #ifdef MESS
  54. static int add_device(struct rc_option *option, const char *arg, int priority);
  55. static int specify_ram(struct rc_option *option, const char *arg, int priority);
  56. #endif
  57.  
  58. /* struct definitions */
  59. static struct rc_option opts[] = {
  60.    /* name, shortname, type, dest, deflt, min, max, func, help */
  61.     { NULL, NULL, rc_link, video_opts, NULL, 0, 0, NULL, NULL },
  62.     { NULL, NULL, rc_link, sound_opts, NULL, 0, 0, NULL, NULL },
  63.     { NULL, NULL, rc_link, input_opts, NULL, 0, 0, NULL, NULL },
  64.     { NULL, NULL, rc_link, network_opts, NULL, 0, 0, NULL, NULL },
  65.     { NULL, NULL, rc_link, fileio_opts, NULL, 0, 0, NULL, NULL },
  66. #ifdef MESS
  67.     /* FIXME - these option->names should NOT be hardcoded! */
  68.     { "MESS specific options", NULL, rc_seperator, NULL, NULL, 0, 0, NULL, NULL },
  69.     { "cartridge", "cart", rc_string, &mess_opts, NULL, 0, 0, add_device, "Attach software to cartridge device" },
  70.     { "floppydisk","flop", rc_string, &mess_opts, NULL, 0, 0, add_device, "Attach software to floppy disk device" },
  71.     { "harddisk",  "hard", rc_string, &mess_opts, NULL, 0, 0, add_device, "Attach software to hard disk device" },
  72.     { "cylinder",  "cyln", rc_string, &mess_opts, NULL, 0, 0, add_device, "Attach software to cylinder device" },
  73.     { "cassette",  "cass", rc_string, &mess_opts, NULL, 0, 0, add_device, "Attach software to cassette device" },
  74.     { "punchcard", "pcrd", rc_string, &mess_opts, NULL, 0, 0, add_device, "Attach software to punch card device" },
  75.     { "punchtape", "ptap", rc_string, &mess_opts, NULL, 0, 0, add_device, "Attach software to punch tape device" },
  76.     { "printer",   "prin", rc_string, &mess_opts, NULL, 0, 0, add_device, "Attach software to printer device" },
  77.     { "serial",    "serl", rc_string, &mess_opts, NULL, 0, 0, add_device, "Attach software to serial device" },
  78.     { "parallel",  "parl", rc_string, &mess_opts, NULL, 0, 0, add_device, "Attach software to parallel device" },
  79.     { "snapshot",  "dump", rc_string, &mess_opts, NULL, 0, 0, add_device, "Attach software to snapshot device" },
  80.     { "quickload", "quik", rc_string, &mess_opts, NULL, 0, 0, add_device, "Attach software to quickload device" },
  81.     { "ramsize", "ram", rc_string, &mess_opts, NULL, 0, 0, specify_ram, "Specifies size of RAM (if supported by driver)" },
  82. #else
  83.     { "MAME Related", NULL, rc_seperator, NULL, NULL, 0, 0, NULL, NULL },
  84.     { "defaultgame", "def", rc_string, &defaultgamename, "pacman", 0, 0, NULL, "Set the default game started when no game is given on the commandline, only useful for in the configfiles" },
  85. #endif
  86.     { "language", "lang", rc_string, &language, "english", 0, 0, NULL, "Select the language for the menus and osd" },
  87.     { "fuzzycmp", "fc", rc_bool, &use_fuzzycmp, "1", 0, 0, NULL, "Enable/disable use of fuzzy gamename matching when there is no exact match" },
  88.     { "cheat", "c", rc_bool, &options.cheat, "0", 0, 0, NULL, "Enable/disable cheat subsystem" },
  89.     { "skip_disclaimer", NULL, rc_bool, &options.skip_disclaimer, "0", 0, 0, NULL, "Skip displaying the disclaimer screen" },
  90.     { "skip_gameinfo", NULL, rc_bool, &options.skip_gameinfo, "0", 0, 0, NULL, "Skip displaying the game info screen" },
  91.     { "crconly", NULL, rc_bool, &options.crc_only, "0", 0, 0, NULL, "Use only CRC for all integrity checks" },
  92.     { "bios", NULL, rc_string, &options.bios, "default", 0, 14, NULL, "change system bios" },
  93. #ifdef MAME_DEBUG
  94.     { "debug", "d", rc_bool, &options.mame_debug, NULL, 0, 0, NULL, "Enable/disable debugger" },
  95.     { "debug-size", "ds", rc_use_function, NULL, "640x480", 0, 0, config_handle_debug_size, "Specify the resolution/window size to use for the debugger (window) in the form of XRESxYRES (minimum size = 640x480)" },
  96. #endif
  97.     { NULL, NULL, rc_link, frontend_list_opts, NULL, 0, 0, NULL, NULL },
  98.     { NULL, NULL, rc_link, frontend_ident_opts, NULL, 0, 0, NULL, NULL },
  99.     { "General Options", NULL, rc_seperator, NULL, NULL, 0, 0, NULL, NULL },
  100.     { "loadconfig", "lcf", rc_bool, &loadconfig, "1", 0, 0, NULL, "Load (don't load) configfiles" },
  101.     { "showconfig", "sc", rc_set_int, &showconfig, NULL, 1, 0, NULL, "Display running parameters in rc style" },
  102.     { "manhelp", "mh", rc_set_int, &showmanusage, NULL, 1, 0, NULL, "Print commandline help in man format, useful for manpage creation" },
  103.     { "version", "V", rc_set_int, &showversion, NULL, 1, 0, NULL, "Display version" },
  104.     { "help", "?", rc_set_int, &showusage, NULL, 1, 0, NULL, "Show this help" },
  105.     { NULL, NULL, rc_end, NULL, NULL, 0, 0, NULL, NULL }
  106. };
  107.  
  108. /* fuzzy string compare, compare short string against long string        */
  109. /* e.g. astdel == "Asteroids Deluxe". The return code is the fuzz index, */
  110. /* we simply count the gaps between maching chars.                       */
  111. static int fuzzycmp (const char *s, const char *l)
  112. {
  113.     int gaps = 0;
  114.     int match = 0;
  115.     int last = 1;
  116.  
  117.     for (; *s && *l; l++)
  118.     {
  119.         if (*s == *l)
  120.             match = 1;
  121.         else if (*s >= 'a' && *s <= 'z' && (*s - 'a') == (*l - 'A'))
  122.             match = 1;
  123.         else if (*s >= 'A' && *s <= 'Z' && (*s - 'A') == (*l - 'a'))
  124.             match = 1;
  125.         else
  126.             match = 0;
  127.  
  128.         if (match)
  129.             s++;
  130.  
  131.         if (match != last)
  132.         {
  133.             last = match;
  134.             if (!match)
  135.                 gaps++;
  136.         }
  137.     }
  138.  
  139.     /* penalty if short string does not completely fit in */
  140.     for (; *s; s++)
  141.         gaps++;
  142.  
  143.     return gaps;
  144. }
  145.  
  146. #ifndef MESS
  147. /* for verify roms which is used for the random game selection */
  148. static int config_printf(const char *fmt, ...)
  149. {
  150.     return 0;
  151. }
  152. #endif
  153.  
  154. static int config_handle_arg(char *arg)
  155. {
  156.     static int got_gamename = 0;
  157.  
  158.     if (!got_gamename) /* notice: for MESS game means system */
  159.     {
  160.         gamename     = arg;
  161.         got_gamename = 1;
  162.     }
  163.     else
  164. #ifdef MESS
  165.     {
  166.         if( options.image_count >= MAX_IMAGES )
  167.         {
  168.             fprintf(stderr, "error: too many image names specified!\n");
  169.             return -1;
  170.         }
  171.         /* options.image_files[options.image_count].type = iodevice_type; */
  172.         /* options.image_files[options.image_count].name = arg; */
  173.         /* options.image_count++; */
  174.     }
  175. #else
  176.     {
  177.         fprintf(stderr,"error: duplicate gamename: %s\n", arg);
  178.         return -1;
  179.     }
  180. #endif
  181.  
  182.     return 0;
  183. }
  184.  
  185. #ifdef MAME_DEBUG
  186. static int config_handle_debug_size(struct rc_option *option, const char *arg,
  187.         int priority)
  188. {
  189.     int width, height;
  190.  
  191.     if (sscanf(arg, "%dx%d", &width, &height) == 2)
  192.     {
  193.         if((width >= 640) && (height >= 480))
  194.         {
  195.             options.debug_width  = width;
  196.             options.debug_height = height;
  197.             return 0;
  198.         }
  199.     }
  200.     fprintf(stderr,
  201.             "error: invalid debugger size or too small (minimum size = 640x480): \"%s\".\n",
  202.             arg);
  203.     return -1;
  204. }
  205. #endif /* MAME_DEBUG */
  206.  
  207. #ifdef MESS
  208. int xmess_printf_output(const char *fmt, va_list arg)
  209. {
  210.     return vfprintf(stderr_file, fmt, arg);
  211. }
  212. #endif /* MESS */
  213.  
  214. /*
  215.  * get configuration from configfile and env.
  216.  */
  217. int config_init (int argc, char *argv[])
  218. {
  219.     char buffer[BUF_SIZE];
  220.     unsigned char lsb_test[2]={0,1};
  221.     int i;
  222.  
  223.     memset(&options,0,sizeof(options));
  224.  
  225.     /* reset trackball devices */
  226. #ifdef USE_XINPUT_DEVICES
  227.     XInput_trackballs_reset();
  228. #endif
  229.  
  230.     /* Let's see if the endianess of this arch is correct; otherwise,
  231.        YELL about it and bail out. */
  232. #ifdef LSB_FIRST
  233.     if(*((unsigned short*)lsb_test) != 0x0100)
  234. #else    
  235.     if(*((unsigned short*)lsb_test) != 0x0001)
  236. #endif
  237.     {
  238.         fprintf(stderr, "error: compiled byte ordering doesn't match machine byte ordering\n"
  239.                 "are you sure you choose the right arch?\n"
  240. #ifdef LSB_FIRST
  241.                 "compiled for lsb-first, are you sure you choose the right cpu in makefile.unix\n");
  242. #else
  243.                 "compiled for msb-first, are you sure you choose the right cpu in makefile.unix\n");
  244. #endif
  245.         return OSD_NOT_OK;
  246.     }
  247.  
  248.     /* some settings which are static for xmame and thus aren't controled
  249.        by options */
  250.     options.gui_host = 1;
  251. #ifdef MESS
  252.     options.mess_printf_output = xmess_printf_output;
  253. #endif
  254.     cheatfile = NULL;
  255.     db_filename = NULL;
  256.     history_filename = NULL;
  257.     mameinfo_filename = NULL;
  258.  
  259.     /* create the rc object */
  260.     if (!(rc = rc_create()))
  261.         return OSD_NOT_OK;
  262.  
  263.     if(sysdep_dsp_init(rc, NULL))
  264.         return OSD_NOT_OK;
  265.  
  266.     if(sysdep_mixer_init(rc, NULL))
  267.         return OSD_NOT_OK;
  268.  
  269.     if(rc_register(rc, opts))
  270.         return OSD_NOT_OK;
  271.  
  272.     /* get the homedir */
  273.     if(!(home_dir = rc_get_home_dir()))
  274.         return OSD_NOT_OK;
  275.  
  276.     /* check that the required dirs exist, and create them if necessary */
  277. #ifdef __amigaos4__
  278.     snprintf(buffer, BUF_SIZE, "%s.%s", home_dir, NAME);
  279.     if (rc_check_and_create_dir(buffer))
  280.         return OSD_NOT_OK;
  281.  
  282.     snprintf(buffer, BUF_SIZE, "%s.%s/%s", home_dir, NAME, "cfg");
  283.     if (rc_check_and_create_dir(buffer))
  284.         return OSD_NOT_OK;
  285.  
  286.     snprintf(buffer, BUF_SIZE, "%s.%s/%s", home_dir, NAME, "mem");
  287.     if (rc_check_and_create_dir(buffer))
  288.         return OSD_NOT_OK;
  289.  
  290.     snprintf(buffer, BUF_SIZE, "%s.%s/%s", home_dir, NAME, "sta");
  291.     if (rc_check_and_create_dir(buffer))
  292.         return OSD_NOT_OK;
  293.  
  294.     snprintf(buffer, BUF_SIZE, "%s.%s/%s", home_dir, NAME, "nvram");
  295.     if (rc_check_and_create_dir(buffer))
  296.         return OSD_NOT_OK;
  297.  
  298.     snprintf(buffer, BUF_SIZE, "%s.%s/%s", home_dir, NAME, "diff");
  299.     if (rc_check_and_create_dir(buffer))
  300.         return OSD_NOT_OK;
  301.  
  302.     snprintf(buffer, BUF_SIZE, "%s.%s/%s", home_dir, NAME, "rc");
  303.     if (rc_check_and_create_dir(buffer))
  304.         return OSD_NOT_OK;
  305.  
  306.     snprintf(buffer, BUF_SIZE, "%s.%s/%s", home_dir, NAME, "hi");
  307.     if (rc_check_and_create_dir(buffer))
  308.         return OSD_NOT_OK;
  309.  
  310.     snprintf(buffer, BUF_SIZE, "%s.%s/%s", home_dir, NAME, "inp");
  311.     if (rc_check_and_create_dir(buffer))
  312.         return OSD_NOT_OK;
  313. #else
  314.     snprintf(buffer, BUF_SIZE, "%s.%s", home_dir, NAME);
  315.     if (rc_check_and_create_dir(buffer))
  316.         return OSD_NOT_OK;
  317.  
  318.     snprintf(buffer, BUF_SIZE, "%s.%s/%s", home_dir, NAME, "cfg");
  319.     if (rc_check_and_create_dir(buffer))
  320.         return OSD_NOT_OK;
  321.  
  322.     snprintf(buffer, BUF_SIZE, "%s.%s/%s", home_dir, NAME, "mem");
  323.     if (rc_check_and_create_dir(buffer))
  324.         return OSD_NOT_OK;
  325.  
  326.     snprintf(buffer, BUF_SIZE, "%s.%s/%s", home_dir, NAME, "sta");
  327.     if (rc_check_and_create_dir(buffer))
  328.         return OSD_NOT_OK;
  329.  
  330.     snprintf(buffer, BUF_SIZE, "%s.%s/%s", home_dir, NAME, "nvram");
  331.     if (rc_check_and_create_dir(buffer))
  332.         return OSD_NOT_OK;
  333.  
  334.     snprintf(buffer, BUF_SIZE, "%s.%s/%s", home_dir, NAME, "diff");
  335.     if (rc_check_and_create_dir(buffer))
  336.         return OSD_NOT_OK;
  337.  
  338.     snprintf(buffer, BUF_SIZE, "%s.%s/%s", home_dir, NAME, "rc");
  339.     if (rc_check_and_create_dir(buffer))
  340.         return OSD_NOT_OK;
  341.  
  342.     snprintf(buffer, BUF_SIZE, "%s.%s/%s", home_dir, NAME, "hi");
  343.     if (rc_check_and_create_dir(buffer))
  344.         return OSD_NOT_OK;
  345.  
  346.     snprintf(buffer, BUF_SIZE, "%s.%s/%s", home_dir, NAME, "inp");
  347.     if (rc_check_and_create_dir(buffer))
  348.         return OSD_NOT_OK;
  349. #endif
  350.  
  351.     /* parse the commandline */
  352.     if (rc_parse_commandline(rc, argc, argv, 2, config_handle_arg))
  353.         return OSD_NOT_OK;
  354.  
  355.     /* parse the various configfiles, starting with the one with the
  356.        lowest priority */
  357.     if(loadconfig)
  358.     {
  359.         snprintf(buffer, BUF_SIZE, "%s%src", XMAMEROOT, NAME);
  360.  
  361.         if(rc_load(rc, buffer, 1, 1))
  362.             return OSD_NOT_OK;
  363.         snprintf(buffer, BUF_SIZE, "%s.%s/%src", home_dir, NAME, NAME);
  364.  
  365.         if(rc_load(rc, buffer, 1, 1))
  366.             return OSD_NOT_OK;
  367.         snprintf(buffer, BUF_SIZE, "%s%s-%src", XMAMEROOT, NAME, DISPLAY_METHOD);
  368.         if(rc_load(rc, buffer, 1, 1))
  369.             return OSD_NOT_OK;
  370.         snprintf(buffer, BUF_SIZE, "%s.%s/%s-%src", home_dir, NAME, NAME,
  371.                 DISPLAY_METHOD);
  372.         if(rc_load(rc, buffer, 1, 1))
  373.             return OSD_NOT_OK;
  374.     }
  375.  
  376.     /* setup stderr_file and stdout_file */
  377.     if (!stderr_file) stderr_file = stderr;
  378.     if (!stdout_file) stdout_file = stdout;
  379.  
  380.     effect_init1();
  381.  
  382.     if (showconfig)
  383.     {
  384.         rc_write(rc, stdout_file, NAME" running parameters");
  385.         return OSD_OK;
  386.     }
  387.  
  388.     if (showmanusage)
  389.     {
  390.         rc_print_man_options(rc, stdout_file);
  391.         return OSD_OK;
  392.     }
  393.  
  394.     if (showversion)
  395.     {
  396.         fprintf(stdout_file, "%s\n", title);
  397.         return OSD_OK;
  398.     }
  399.  
  400.     if (showusage)
  401.     {
  402.         show_usage();
  403.         return OSD_OK;
  404.     }
  405.  
  406.     /* handle frontend options */
  407.     if ( (i=frontend_list(gamename)) != 1234)
  408.         return i;
  409.  
  410.     if ( (i=frontend_ident(gamename)) != 1234)
  411.         return i;
  412.  
  413.     if (playbackname)
  414.     {
  415.         options.playback = mame_fopen(playbackname, 0, FILETYPE_INPUTLOG, 0);
  416.         if (!options.playback)
  417.         {
  418.             fprintf(stderr, "failed to open %s for playback\n", playbackname);
  419.             exit(1);
  420.         }
  421.     }
  422.  
  423.     /* check for game name embedded in .inp header */
  424.     if (options.playback)
  425.     {
  426.         INP_HEADER inp_header;
  427.  
  428.         /* read playback header */
  429.         mame_fread(options.playback, &inp_header, sizeof(INP_HEADER));
  430.  
  431.         if (!isalnum(inp_header.name[0])) /* If first byte is not alpha-numeric */
  432.             mame_fseek(options.playback, 0, SEEK_SET); /* old .inp file - no header */
  433.         else
  434.         {
  435.             for (i = 0; (drivers[i] != 0); i++) /* find game and play it */
  436.             {
  437.                 if (strcmp(drivers[i]->name, inp_header.name) == 0)
  438.                 {
  439.                     game_index = i;
  440.                     gamename = (char *)drivers[i]->name;
  441.                     printf("Playing back previously recorded game %s (%s) [press return]\n",
  442.                             drivers[game_index]->name,drivers[game_index]->description);
  443.                     getchar();
  444.                     break;
  445.                 }
  446.             }
  447.         }
  448.     }
  449.  
  450.     /* handle the game selection */
  451.     game_index = -1;
  452.  
  453.     if (!gamename)
  454. #ifdef MESS
  455.     {
  456.         show_usage();
  457.         return OSD_NOT_OK;
  458.     }
  459. #else
  460.     gamename = defaultgamename;
  461.  
  462.     /* random game? */
  463.     if (strcasecmp(gamename, "random") == 0)
  464.     {
  465.         for (i=0; drivers[i]; i++) ; /* count available drivers */
  466.  
  467.         srand(time(NULL));
  468.  
  469.         for(;;)
  470.         {
  471.             game_index = (float)rand()*i/RAND_MAX;
  472.  
  473.             fprintf(stdout_file, "Random game selected: %s (%s)\n  verifying roms... ",drivers[game_index]->name,drivers[game_index]->description);
  474.             if(VerifyRomSet (game_index, (verify_printf_proc)config_printf) == CORRECT)
  475.             {
  476.                 fprintf(stdout_file, "OK\n");
  477.                 break;
  478.             }
  479.             else
  480.                 fprintf(stdout_file, "FAILED\n");
  481.         }
  482.     }
  483.     else
  484. #endif
  485.         /* do we have a driver for this? */
  486. #ifdef MESS
  487.         for (i = 0; drivers[i]; i++)
  488.         {
  489.             if (strcasecmp(gamename,drivers[i]->name) == 0)
  490.             {
  491.                 game_index = i;
  492.                 break;
  493.             }
  494.         }
  495. #else
  496.     {
  497.         char *begin = strrchr(gamename, '/'), *end;
  498.         int len;
  499.  
  500.         if (begin == 0)
  501.             begin = gamename;
  502.         else
  503.             begin++;
  504.  
  505.         end = strchr(begin, '.');
  506.         if (end == 0)
  507.             len = strlen(begin);
  508.         else
  509.             len = end - begin;            
  510.  
  511.         for (i = 0; drivers[i]; i++)
  512.         {
  513.             if (strncasecmp(begin, drivers[i]->name, len) == 0 
  514.                     && len == strlen(drivers[i]->name))
  515.             {
  516.                 begin = strrchr(gamename,'/');
  517.                 if (begin)
  518.                 {
  519.                     *begin='\0'; /* dynamic allocation and copying will be better */
  520.                     rompath_extra = malloc(strlen(gamename) + 1);
  521.                     strcpy(rompath_extra, gamename);
  522.                 }
  523.                 game_index = i;
  524.                 break;
  525.             }
  526.         }
  527.     }
  528. #endif                                
  529.  
  530.     /* educated guess on what the user wants to play */
  531.     if ( (game_index == -1) && use_fuzzycmp)
  532.     {
  533.         int fuzz = 9999; /*best fuzz factor so far*/
  534.  
  535.         for (i = 0; (drivers[i] != 0); i++)
  536.         {
  537.             int tmp;
  538.             tmp = fuzzycmp(gamename, drivers[i]->description);
  539.             /* continue if the fuzz index is worse */
  540.             if (tmp > fuzz)
  541.                 continue;
  542.             /* on equal fuzz index, we prefear working, original games */
  543.             if (tmp == fuzz)
  544.             {
  545.                 /* game is a clone */
  546.                 if (drivers[i]->clone_of != 0 && !(drivers[i]->clone_of->flags & NOT_A_DRIVER))
  547.                 {
  548.                     if ((!drivers[game_index]->flags & GAME_NOT_WORKING) || (drivers[i]->flags & GAME_NOT_WORKING))
  549.                         continue;
  550.                 }
  551.                 else continue;
  552.             }
  553.  
  554.  
  555.             /* we found a better match */
  556.             game_index = i;
  557.             fuzz = tmp;
  558.         }
  559.  
  560.         if (game_index != -1)
  561.             fprintf(stdout_file,
  562.                     "fuzzy name compare, running %s\n", drivers[game_index]->name);
  563.     }
  564.  
  565.     if (game_index == -1)
  566.     {
  567.         fprintf(stderr_file, "\"%s\" not supported\n", gamename);
  568.         return OSD_NOT_OK;
  569.     }
  570.  
  571.     /* now that we've got the gamename parse the game specific configfile */
  572.     if (loadconfig)
  573.     {
  574.         snprintf(buffer, BUF_SIZE, "%src/%src", XMAMEROOT,
  575.                 drivers[game_index]->name);
  576.         if(rc_load(rc, buffer, 1, 1))
  577.             return OSD_NOT_OK;
  578.         snprintf(buffer, BUF_SIZE, "%s.%s/rc/%src", home_dir, NAME,
  579.                 drivers[game_index]->name);
  580.         if(rc_load(rc, buffer, 1, 1))
  581.             return OSD_NOT_OK;
  582.     }
  583.  
  584. #ifdef MESS
  585.     /* set the image type if necessary */
  586.     for(i=0; i<options.image_count; i++)
  587.     {
  588.         if(options.image_files[i].type)
  589.         {
  590.             logerror("User specified %s for %s\n",
  591.                     device_typename(options.image_files[i].type),
  592.                     options.image_files[i].name);
  593.         }
  594.         else
  595.         {
  596.             char *ext;
  597.             char name[BUF_SIZE];
  598.             const struct IODevice *dev;
  599.  
  600.             /* make a copy of the name */
  601.             strncpy(name, options.image_files[i].name, BUF_SIZE);
  602.             /* strncpy is buggy */
  603.             name[BUF_SIZE-1]=0;
  604.  
  605.             /* get ext, skip .gz */
  606.             ext = strrchr(name, '.');
  607.             if (ext && !strcmp(ext, ".gz"))
  608.             {
  609.                 *ext = 0;
  610.                 ext = strrchr(name, '.');
  611.             }
  612.  
  613.             /* Look up the filename extension in the drivers device list */
  614.             if (ext && (dev = device_first(drivers[game_index])))
  615.             {
  616.                 ext++; /* skip the "." */
  617.  
  618.                 while (dev)
  619.                 {
  620.                     const char *dst = dev->file_extensions;
  621.                     /* scan supported extensions for this device */
  622.                     while (dst && *dst)
  623.                     {
  624.                         if (strcasecmp(dst,ext) == 0)
  625.                         {
  626.                             logerror("Extension match %s [%s] for %s\n",
  627.                                     device_typename(dev->type), dst,
  628.                                     options.image_files[i].name);
  629.  
  630.                             options.image_files[i].type = dev->type;
  631.                         }
  632.                         /* skip '\0' once in the list of extensions */
  633.                         dst += strlen(dst) + 1;
  634.                     }
  635.                     dev = device_next(drivers[game_index], dev); 
  636.                 }
  637.             }
  638.             if(!options.image_files[i].type)
  639.                 options.image_files[i].type = IO_CARTSLOT;
  640.         }
  641.     }
  642. #endif
  643.  
  644.     if (recordname)
  645.     {
  646.         options.record = mame_fopen(recordname, 0, FILETYPE_INPUTLOG, 1);
  647.         if (!options.record)
  648.         {
  649.             fprintf(stderr_file, "failed to open %s for recording\n", recordname);
  650.             exit(1);
  651.         }
  652.     }
  653.  
  654.     if (options.record)
  655.     {
  656.         INP_HEADER inp_header;
  657.  
  658.         memset(&inp_header, '\0', sizeof(INP_HEADER));
  659.         strcpy(inp_header.name, drivers[game_index]->name);
  660.         mame_fwrite(options.record, &inp_header, sizeof(INP_HEADER));
  661.     }
  662.  
  663. //       if (statename)
  664. //              options.savegame = statename;
  665.  
  666.     if(language)
  667.         options.language_file = mame_fopen(0,language,FILETYPE_LANGUAGE,0);
  668.  
  669.     return 1234;
  670. }
  671.  
  672. void config_exit(void)
  673. {
  674.     if(rc)
  675.     {
  676.         sysdep_mixer_exit();
  677.         sysdep_dsp_exit();
  678.         rc_destroy(rc);
  679.     }
  680.  
  681.     if(home_dir)
  682.         free(home_dir);
  683.  
  684.     /* close open files */
  685.     if (options.playback)
  686.         mame_fclose(options.playback);
  687.     if (options.record)
  688.         mame_fclose(options.record);
  689.     if (options.language_file)
  690.         mame_fclose(options.language_file);
  691. }
  692.  
  693. /* 
  694.  * show help and exit
  695.  */
  696. void show_usage(void) 
  697. {
  698.     /* header */
  699.     fprintf(stdout_file, 
  700. #ifdef MESS
  701.             "Usage: xmess <system> [game] [options]\n"
  702. #else
  703.             "Usage: xmame [game] [options]\n"
  704. #endif 
  705.             "Options:\n");
  706.  
  707.     /* actual help message */
  708.     rc_print_help(rc, stdout_file);
  709.  
  710.     /* footer */
  711.     fprintf(stdout_file, "\nFiles:\n\n");
  712.     fprintf(stdout_file, "Config Files are parsed in the following order:\n");
  713.     fprint_columns(stdout_file, XMAMEROOT"/"NAME"rc",
  714.             "Global configuration config file");
  715.     fprint_columns(stdout_file, "${HOME}/."NAME"/"NAME"rc",
  716.             "User configuration config file");
  717.     fprint_columns(stdout_file, XMAMEROOT"/"NAME"-"DISPLAY_METHOD"rc",
  718.             "Global per display method config file");
  719.     fprint_columns(stdout_file, "${HOME}/."NAME"/"NAME"-"DISPLAY_METHOD"rc",
  720.             "User per display method config file");
  721.     fprint_columns(stdout_file, XMAMEROOT"/rc/<game>rc",
  722.             "Global per game config file");
  723.     fprint_columns(stdout_file, "${HOME}/."NAME"/rc/<game>rc",
  724.             "User per game config file");
  725.     /*  fprintf(stdout_file, "\nEnvironment variables:\n\n");
  726.         fprint_columns(stdout_file, "ROMPATH", "Rom search path"); */
  727.     fprintf(stdout_file, "\n"
  728. #ifdef MESS
  729.             "M.E.S.S. - Multi-Emulator Super System\n"
  730.             "Copyright (C) 1998-2004 by the MESS team\n"
  731. #else
  732.             "M.A.M.E. - Multiple Arcade Machine Emulator\n"
  733.             "Copyright (C) 1997-2004 by Nicola Salmoria and the MAME Team\n"
  734. #endif
  735.             "%s port maintained by Lawrence Gold\n", NAME);
  736. }
  737.  
  738. #ifdef MESS
  739.  
  740. /*    add_device() is called when the MESS CLI option has been identified
  741.  *    This searches throught the devices{} struct array to grab the ID of the
  742.  *    option, which then registers the device using register_device()
  743.  */
  744. static int add_device(struct rc_option *option, const char *arg, int priority)
  745. {
  746.     int id;
  747.     id = device_typeid(option->name);
  748.     if (id < 0)
  749.     {
  750.         /* If we get to here, log the error - This is mostly due to a mismatch in the array */
  751.         logerror("Command Line Option [-%s] not a valid device - ignoring\n", option->name);
  752.         return -1;
  753.     }
  754.  
  755.     /* A match!  we now know the ID of the device */
  756.     option->priority = priority;
  757.     return register_device(id, arg);
  758. }
  759.  
  760. static int specify_ram(struct rc_option *option, const char *arg, int priority)
  761. {
  762.     UINT32 specified_ram = 0;
  763.  
  764.     if (strcmp(arg, "0"))
  765.     {
  766.         specified_ram = ram_parse_string(arg);
  767.         if (specified_ram == 0)
  768.         {
  769.             fprintf(stderr, "Cannot recognize the RAM option %s; aborting\n", arg);
  770.             return -1;
  771.         }
  772.     }
  773.     options.ram = specified_ram;
  774.     return 0;
  775. }
  776.  
  777. #endif
  778.  
  779.  
  780. /*============================================================ */
  781. /*    logerror */
  782. /*============================================================ */
  783.  
  784. extern FILE *errorlog;
  785.  
  786. void logerror(const char *text, ...)
  787. {
  788.     va_list arg;
  789.  
  790.     if (errorlog)
  791.     {
  792.         va_start(arg, text);
  793.         vfprintf(errorlog, text, arg);
  794.         va_end(arg);
  795.         fflush(errorlog);
  796.     }
  797. }
  798.  
  799.  
  800.